﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;
using System.Web.Routing;
using System.Web.Mvc.Html;
using System.Web.UI;
using System.Web.Compilation;
using System.IO;
using VCommons;
using System.Web.WebPages;
namespace Commons.Web.Helpers
{
    /// <summary>
    /// 存储CSS样式的结构
    /// </summary>
    public struct TagClassStruct
    {
        public TagClassStruct(string selectedClassName) : this(null, selectedClassName) { }
        public TagClassStruct(string liClassName, string selectedClassName)
            : this()
        {
            this.LiClassName = liClassName;
            this.SelectedClassName = selectedClassName;
        }
        public string LiClassName { get; private set; }
        public string SelectedClassName { get; private set; }
    }
    /// <summary>
    /// HTML扩展类型
    /// </summary>
    public static class HtmlExtensions
    {

        #region RequestContext 扩展


        /// <summary>
        /// 是否为当前路由（传入的URL与当前URL是否相同）
        /// </summary>
        /// <param name="context"></param>
        /// <param name="areaName"></param>
        /// <param name="controllerName"></param>
        /// <param name="actionNames"></param>
        /// <returns></returns>
        public static bool IsCurrentRoute(this RequestContext context, String controllerName, String actionName)
        {
            var routeData = context.RouteData;

            if (string.Compare(routeData.GetRequiredString("controller"), controllerName, true) == 0
                && (string.Compare(actionName, routeData.GetRequiredString("action"), true) == 0))
            {
                return true;
            }


            return false;
        }


        #endregion

        #region UrlHelper 扩展


        public static bool IsCurrent(this UrlHelper urlHelper, String controllerName)
        {
            return urlHelper.IsCurrent(controllerName);
        }

        public static bool IsCurrent(this UrlHelper urlHelper, String areaName, String controllerName, String actionName)
        {
            return urlHelper.RequestContext.IsCurrentRoute(controllerName, actionName);
        }

        public static string Selected(this UrlHelper urlHelper, String areaName)
        {
            return urlHelper.Selected(areaName, null, null);
        }

        public static string Selected(this UrlHelper urlHelper, String areaName, String controllerName)
        {
            return urlHelper.Selected(areaName, controllerName, null);
        }

        public static string Selected(this UrlHelper urlHelper, String areaName, String controllerName, String actionName)
        {
            return urlHelper.IsCurrent(areaName, controllerName, actionName) ? "selected" : String.Empty;
        }

        #endregion

        #region HtmlHelper 扩展
        public static MvcHtmlString ActionMenuItem(this HtmlHelper htmlHelper, String linkText, String actionName, String controllerName, TagClassStruct tagClassStruct)
        {
            return ActionMenuItem(htmlHelper, linkText, actionName, controllerName, null, tagClassStruct);
        }
        /// <summary>
        /// 添加导航菜单（当前URL相同是select样式，返回去除select样式）
        /// </summary>  
        /// <param name="htmlHelper"></param>
        /// <param name="linkText"></param>
        /// <param name="actionName"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static MvcHtmlString ActionMenuItem(this HtmlHelper htmlHelper, String linkText, String actionName, String controllerName, object routeValues, TagClassStruct tagClassStruct)
        {
            var tag = new TagBuilder("li");
            if (tagClassStruct.LiClassName != null)
                tag.AddCssClass(tagClassStruct.LiClassName);
            if (htmlHelper.ViewContext.RequestContext.IsCurrentRoute(controllerName, actionName))
            {
                tag.AddCssClass(tagClassStruct.SelectedClassName);
            }
            tag.InnerHtml = htmlHelper.ActionLink(linkText, actionName, controllerName, routeValues).ToString();
            return MvcHtmlString.Create(tag.ToString());
        }
        #endregion

        #region PartialView扩展

        #region 为页面提供的
        public static string RenderPartialToString(this HtmlHelper htmlHelper, string partial)
        {
            return RenderPartialToString(htmlHelper, partial, null);
        }
        /// <summary>
        /// 将指定ascx分部视图的文本内容追加到当前输出流
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="partial">ascx路径</param>
        /// <returns></returns>
        public static string RenderPartialToString(this HtmlHelper htmlHelper, string partial, object model)
        {
            var viewInstance = BuildManager.CreateInstanceFromVirtualPath(partial, typeof(object));
            ViewDataDictionary vd = new ViewDataDictionary(model);
            var control = viewInstance as ViewUserControl;
            control.ViewContext = htmlHelper.ViewContext;
            control.ViewData = vd;// htmlHelper.ViewData;//得到当前viewcontext中的Model
            Page page = new ViewPage();
            page.Controls.Add(control);
            TextWriter writer = new StringWriter();
            htmlHelper.ViewContext.HttpContext.Server.Execute(page, writer, false);
            return writer.ToString();
        }
        #endregion

        #region 为代码层提供的
        /// <summary>
        /// 返回指定ascx分部视图的文本内容
        /// 如果在页面上输出解释后的ＨＴＭＬ，请使用Html.Decode()
        /// </summary>
        /// <param name="partial">ascx路径</param>
        /// <param name="model">视图模型数据</param>
        /// <returns></returns>
        public static string RenderPartialToString(ControllerContext context, string partial, object model)
        {
            ViewEngineResult result = ViewEngines.Engines.FindPartialView(context, partial);
            if (result.View != null)
            {
                ViewDataDictionary vd = new ViewDataDictionary(model);
                StringBuilder sb = new StringBuilder();
                using (StringWriter sw = new StringWriter(sb))
                {
                    using (HtmlTextWriter output = new HtmlTextWriter(sw))
                    {
                        ViewContext viewContext = new ViewContext(context, result.View, vd, new TempDataDictionary(), output);
                        result.View.Render(viewContext, output);
                    }
                }
                return sb.ToString();
            }

            return String.Empty;

        }
        /// <summary>
        ///  返回指定ascx分部视图的文本内容
        /// </summary>
        /// <param name="partial">ascx路径</param>
        /// <returns></returns>
        public static string RenderPartialToString(ControllerContext context, string partial)
        {
            return RenderPartialToString(context, partial, null);
        }
        #endregion

        #endregion

        #region 自定义链接(代提醒的)
        /// <summary>
        /// 有确认功能的链接
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="linkText"></param>
        /// <param name="actionName"></param>
        /// <param name="controllerName"></param>
        /// <param name="routeValues"></param>
        /// <returns></returns>
        public static MvcHtmlString ActionLinkForConfirm(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues)
        {

            StringBuilder str = new StringBuilder();
            str.Append("<script>function linkConfirmFun(){confirmDialog(function () {");
            str.AppendFormat("location.href='{0}';", new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(actionName, controllerName, routeValues));
            str.Append("})}</script>");
            if (!htmlHelper.ViewContext.ViewData.ContainsKey("btn_Confirm"))
            {
                htmlHelper.ViewContext.Writer.Write(str.ToString());
                htmlHelper.ViewContext.ViewData.Add("btn_Confirm", true);
            }

            return MvcHtmlString.Create(string.Format("<a href='javascript:void(0);' onclick='linkConfirmFun()' class='button'>{0}</a>", linkText));
        }
        /// <summary>
        /// 有确认功能的链接
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="linkText"></param>
        /// <param name="actionName"></param>
        /// <returns></returns>
        public static MvcHtmlString ActionLinkForConfirm(this HtmlHelper htmlHelper, string linkText, string actionName)
        {
            return ActionLinkForConfirm(htmlHelper, linkText, actionName, null, null);
        }
        /// <summary>
        /// 有确认功能的链接
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="linkText"></param>
        /// <param name="actionName"></param>
        /// <param name="routeValues"></param>
        /// <returns></returns>
        public static MvcHtmlString ActionLinkForConfirm(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues)
        {
            return ActionLinkForConfirm(htmlHelper, linkText, actionName, null, routeValues);
        }

        #endregion

        #region 自定义链接（将ViewPage内容填充到指定ＤＩＶ中）
        /// <summary>
        /// 自定义链接（将ViewPage内容填充到指定ＤＩＶ中）
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="linkText"></param>
        /// <param name="actionName"></param>
        /// <param name="controllerName"></param>
        /// <param name="primaryKey"></param>
        /// <param name="primaryValue"></param>
        /// <returns></returns>
        public static MvcHtmlString ActionLinkForViewFillToDialog(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string primaryKey, object primaryValue)
        {
            string url = new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(actionName, controllerName);

            StringBuilder str = new StringBuilder();
            str.Append(@"<script>function seeDetailFun(id) {
            $.ajax({
                type: 'POST',
                url: 'mvcUrl',
                data: { primaryKey: id },
                success: function (data) {
                    $('#detail').html(data);
                }
            });
            art.dialog({
                title: '详细信息',
                content: document.getElementById('detail'),
                id: 'D345',
                lock:false
            });}</script>
           <div id='detail' style='display: none'>
           </div>");
            str.Replace("controllerName", controllerName).Replace("actionName", actionName).Replace("primaryKey", primaryKey).Replace("mvcUrl", url);
            if (!htmlHelper.ViewContext.ViewData.ContainsKey("btn_SeeDetail"))
            {
                htmlHelper.ViewContext.Writer.Write(str.ToString());
                htmlHelper.ViewContext.ViewData.Add("btn_SeeDetail", true);//向页面添加viewdata，保存页面上只有同功能的JS方法一个
            }

            return MvcHtmlString.Create(string.Format("<a href='javascript:void(0);' onclick='seeDetailFun(\"{1}\")' class='button'>{0}</a>", linkText, primaryValue));
        }
        /// <summary>
        /// 自定义链接（将ViewPage内容填充到指定ＤＩＶ中）
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="linkText"></param>
        /// <param name="actionName"></param>
        /// <param name="controllerName"></param>
        /// <param name="primaryValue"></param>
        /// <returns></returns>
        public static MvcHtmlString ActionLinkForViewFillToDialog(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object primaryValue)
        {
            return ActionLinkForViewFillToDialog(htmlHelper, linkText, actionName, controllerName, "id", primaryValue);
        }
        #endregion

        #region 页面代码块级权限设计

        public static HelperResult RoleHtmlTags(this HtmlHelper htmlHelper, int role, Func<string, HelperResult> template)
        {
            return RoleHtmlTags(htmlHelper, role, true, null, template);
        }
        /// <summary>
        /// 页面代码块级权限设计
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="role">角色ID，在具体的项目中可以使用更友好的枚举类型</param>
        /// <param name="template">要输出的字符串</param>
        /// <returns></returns>
        public static HelperResult RoleHtmlTags(this HtmlHelper htmlHelper, int role, bool isHidden, string fieldsetName, Func<string, HelperResult> template)
        {
            bool flag = true;
            string js = @"<script>$('#" + fieldsetName + "').find('input').click(function(){alert('#MSG#')});</script>";
            switch (role)
            {
                case 1:
                    if (string.IsNullOrWhiteSpace(VCommons.Http.CookieHelper.Read("eee114", "UserID"))
                 || Convert.ToInt32(VCommons.Http.CookieHelper.Read("eee114", "UserID")) <= 0)
                    {
                        flag = false;
                        js = js.Replace("#MSG#", "只有登陆后才能访问");
                    }
                    break;
                case 2:
                    js = js.Replace("#MSG#", "只有老师才有权限");
                    break;
                case 3:
                    js = js.Replace("#MSG#", "只有管理员才有权限");
                    break;
                default:
                    break;

            }
            if (flag)
            {
                return new HelperResult(writer =>
                    {
                        writer.Write(template.Invoke(null));
                    });
            }
            if (isHidden)
            {
                return null;
            }
            string tags = template.Invoke(null) + js;
            return new HelperResult(writer =>
            {
                writer.Write(tags);
            });
        }
        #endregion

        #region 页面级权限设计

        #endregion

        #region 分部视图级权限设计
        #region Html.Action权限扩展
        /// <summary>
        /// 带权限的分部视图
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="actionName"></param>
        /// <param name="controllerName"></param>
        /// <param name="routeValues"></param>
        /// <param name="role"></param>
        /// <returns></returns>
        public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, string controllerName, object routeValues, int role)
        {
            if (role == 1)
                return ChildActionExtensions.Action(htmlHelper, actionName, controllerName, routeValues);
            return null;
        }
        /// <summary>
        /// 带权限的分部视图
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="actionName"></param>
        /// <param name="roleFlag"></param>
        /// <returns></returns>
        public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, int role)
        {
            return Action(htmlHelper, actionName, null, null, role);
        }
        /// <summary>
        /// 带权限的分部视图
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="actionName"></param>
        /// <param name="routeValues"></param>
        /// <param name="roleFlag"></param>
        /// <returns></returns>
        public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, object routeValues, int role)
        {
            return Action(htmlHelper, actionName, null, routeValues, role);
        }
        #endregion
        #endregion

    }

}
